package com.fitnessrocks.sweattimer.data;

import java.util.concurrent.TimeUnit;

import android.content.Context;

import com.fitnessrocks.sweattimer.R;

public class TabataTimer extends AbstractTimer {

    private static final long TIME_TEN_SECONDS = TimeUnit.SECONDS.toMillis(20);
    private static final long TIME_THIRTY_SECONDS = TimeUnit.SECONDS.toMillis(30);
    private static final long TIME_TWENTY_SECONDS = TimeUnit.SECONDS.toMillis(20);
    private static final long TOTAL_DURATION = 8 * (TIME_TWENTY_SECONDS /* work */ + TIME_TEN_SECONDS /* rest */);
    private static final int TOTAL_INTERVALS = 8 /* work */ + 8 /* rest */;
    private static final int TOTAL_SESSIONS = 8;

    protected TabataTimer(Context context) {
        super(context, context.getString(R.string.timer_tabata_name));
    }

    @Override
    public long getIntervalDuration(int intervalIndex) {
        switch (getIntervalType(intervalIndex)) {
        case REST:
            return TIME_TEN_SECONDS;
        case WORK:
            return TIME_TWENTY_SECONDS;
        default:
        }
        return 0;
    }

    @Override
    public int getIntervalIndex(long timeInMillis) {
        if (timeInMillis > getTotalDuration()) {
            return -1;
        }
        int session = (int)(timeInMillis / TIME_THIRTY_SECONDS);
        long withinSequence = getSessionTimeLapsed(timeInMillis);
        if (withinSequence < TIME_TWENTY_SECONDS) {
            return session * 2;
        }
        return session * 2 + 1;
    }

    @Override
    public long getIntervalTimeLapsed(long timeInMillis) {
        if (timeInMillis > getTotalDuration()) {
            return -1;
        }
        long withinSequence = getSessionTimeLapsed(timeInMillis);
        if (withinSequence < TIME_TWENTY_SECONDS) {
            return withinSequence;
        }
        return withinSequence - TIME_TWENTY_SECONDS;
    }

    @Override
    public long getIntervalTimeLeft(long timeInMillis) {
        int intervalIndex = getIntervalIndex(timeInMillis);
        long intervalTimeLapsed = getIntervalTimeLapsed(timeInMillis);
        return getIntervalDuration(intervalIndex) - intervalTimeLapsed;
     }

    @Override
    public IntervalType getIntervalType(int intervalIndex) {
        if (intervalIndex >= 16) {
            return IntervalType.OTHER;
        }
        if (intervalIndex % 2 == 0) {
            return IntervalType.WORK;
        }
        return IntervalType.REST;
    }

    @Override
    public int getSessionIndex(long timeInMillis) {
        return (int) (timeInMillis / TIME_THIRTY_SECONDS);
    }

    @Override
    public String getSessionName(int sessionIndex) {
        if (sessionIndex < 0) {
            sessionIndex = 0;
        }
        if (sessionIndex >= 8) {
            sessionIndex = 7;
        }
        String[] array = mContext.getResources().getStringArray(R.array.timer_tabata_sessions);
        return array[sessionIndex];
    }

    @Override
    public long getSessionTimeLapsed(long timeInMillis) {
        return (timeInMillis % TIME_THIRTY_SECONDS);
    }

    @Override
    public long getSessionTimeLeft(long timeInMillis) {
        return TIME_THIRTY_SECONDS - getSessionTimeLapsed(timeInMillis);
    }

    @Override
    public long getTotalDuration() {
        return TOTAL_DURATION;
    }

    @Override
    public int getTotalIntervals() {
        return TOTAL_INTERVALS;
    }

    @Override
    public int getTotalIntervalsLapsed(int intervalIndex) {
        return intervalIndex;
    }

    @Override
    public int getTotalIntervalsLeft(int intervalIndex) {
        return getTotalIntervals() - intervalIndex;
    }

    @Override
    public int getTotalSessions() {
        return TOTAL_SESSIONS;
    }

    @Override
    public int getTotalSessionsLapsed(int sessionIndex) {
        return sessionIndex;
    }

    @Override
    public int getTotalSessionsLeft(int sessionIndex) {
        return getTotalSessions() - sessionIndex;
    }

    @Override
    public long getTotalTimeLapsed(long timeInMillis) {
        return timeInMillis;
    }

    @Override
    public long getTotalTimeLeft(long timeInMillis) {
        return getTotalDuration() - timeInMillis;
    }

}
